#ifndef GAMEENGINE_GEOMETRY_TOPOLOGY_HALFEDGE_ACCESSOR_H
#define GAMEENGINE_GEOMETRY_TOPOLOGY_HALFEDGE_ACCESSOR_H

#include <GameEngine/Geometry/geometry_settings.h>

#include <GameEngine/Geometry/Topology/halfedge.h>


#ifdef GAMEENGINE_NAMESPACES
namespace GameEngine {
#endif

template <class T> class HalfEdgeFaceAccessor;
template <class T> class HalfEdgeVertexAccessor;
template <class T> class HalfEdgeMesh;

//=================================================================================

//! Class used to provide read-only access to half-edges in a safe manner
/*!
 *  This class provides access to half-edges as references, rather than as pointers.
 *
 *  This type of access is safer than the basic half-edge accessors, not in the sense that
 *  it prevents application crashes (application will still crash when trying to access an
 *  invalid half-edge), but in the sense that application immediately crashes when an incorrect
 *  access is queried (rather than crashing much later on an unrelated function, due to an
 *  invalid pointer access).
 *
 *  This class acts as a wrapper to the half-edge interface, which comes with some limitations:<br>
 *  1. The accessor results in a slight overhead in data access, which has an impact (hopefully
 *     limited) on performance, and<br>
 *  2. The accessor must mimmick the interface of the half-edge (since it does not provide direct
 *     access to the half-edge), which is more difficult to maintain when changes are brought to
 *     the half-edge class (i.e., new features of the half-edge class have to be manually added
 *     to the accessor class).
 *
 *  These limitations are generally considered as insignificant as compared to the benefits of this
 *  class. If performance really matters, however, or if some of the half-edge features are not
 *  provided by the accessor, direct access to the half-edge class should be used rather than
 *  pointer-safe access. This type of design should be directly enforced at a higher level, typically
 *  on the half-edge mesh.
 *
 @sa The HalfEdge class that represents half-edges.
 */
template <class T>
class HalfEdgeAccessor {
	//! The half-edge accessor class is friend of the HalfEdgeMesh class to enable direct data access
	friend class HalfEdgeMesh< HalfEdge<T> >;

public:
	HalfEdgeAccessor(const HalfEdge<T>& edge);
	virtual ~HalfEdgeAccessor();

	bool exterior_edge() const;

	HalfEdgeVertexAccessor<T> origin() const;
	HalfEdgeFaceAccessor<T> face() const;
	HalfEdgeAccessor next_edge() const;
	HalfEdgeAccessor opposite_edge() const;

private:
	HalfEdgeAccessor(const HalfEdgeAccessor& rhs);
	HalfEdgeAccessor& operator=(const HalfEdgeAccessor& rhs);

protected:
	//! Edge associated to this accessor
	const HalfEdge<T>& edge_;
};

//=================================================================================

//! Class used to provide read-only access to half-edge faces in a safe manner
/*!
 *  This class provides access to half-edge faces as references, rather than as pointers.
 *
 *  This type of access is safer than the basic half-edge face accessors, not in the sense that
 *  it prevents application crashes (application will still crash when trying to access an
 *  invalid half-edge face), but in the sense that application immediately crashes when an incorrect
 *  access is queried (rather than crashing much later on an unrelated function, due to an
 *  invalid pointer access).
 *
 *  This class acts as a wrapper to the half-edge face interface, which comes with some limitations:<br>
 *  1. The accessor results in a slight overhead in data access, which has an impact (hopefully
 *     limited) on performance, and<br>
 *  2. The accessor must mimmick the interface of the half-edge face (since it does not provide direct
 *     access to the half-edge face), which is more difficult to maintain when changes are brought to
 *     the half-edge face class (i.e., new features of the half-edge face class have to be manually
 *     added to the accessor class).
 *
 *  These limitations are generally considered as insignificant as compared to the benefits of this
 *  class. If performance really matters, however, or if some of the half-edge face features are not
 *  provided by the accessor, direct access to the half-edge face class should be used rather than
 *  pointer-safe access. This type of design should be directly enforced at a higher level, typically
 *  on the half-edge mesh.
 *
 @sa The HalfEdgeFace class that represents half-edge faces.
 */
template <class T>
class HalfEdgeFaceAccessor {
	//! The half-edge face accessor class is friend of the HalfEdgeMesh class to enable direct data access
	friend class HalfEdgeMesh< HalfEdge<T> >;

public:
	HalfEdgeFaceAccessor(const HalfEdgeFace<T>& face);
	virtual ~HalfEdgeFaceAccessor();

	HalfEdgeAccessor<T> edge() const;

	typename HalfEdgeFace<T>::FaceType face_type() const;
	typename HalfEdgeFace<T>::AdjacencyType adjacency_type() const;

private:
	HalfEdgeFaceAccessor(const HalfEdgeFaceAccessor& rhs);
	HalfEdgeFaceAccessor& operator=(const HalfEdgeFaceAccessor& rhs);

protected:
	//! Face associated to this accessor
	const HalfEdgeFace<T>& face_;
};

//=================================================================================

//! Class used to provide read-only access to half-edge vertices in a safe manner
/*!
 *  This class provides access to half-edge vertices as references, rather than as pointers.
 *
 *  This type of access is safer than the basic half-edge vertex accessors, not in the sense that
 *  it prevents application crashes (application will still crash when trying to access an
 *  invalid half-edge vertex), but in the sense that application immediately crashes when an incorrect
 *  access is queried (rather than crashing much later on an unrelated function, due to an
 *  invalid pointer access).
 *
 *  This class acts as a wrapper to the half-edge vertex interface, which comes with some limitations:<br>
 *  1. The accessor results in a slight overhead in data access, which has an impact (hopefully
 *     limited) on performance, and<br>
 *  2. The accessor must mimmick the interface of the half-edge vertex (since it does not provide direct
 *     access to the half-edge vertex), which is more difficult to maintain when changes are brought to
 *     the half-edge vertex class (i.e., new features of the half-edge vertex class have to be manually
 *     added to the accessor class).
 *
 *  These limitations are generally considered as insignificant as compared to the benefits of this
 *  class. If performance really matters, however, or if some of the half-edge vertex features are not
 *  provided by the accessor, direct access to the half-edge vertex class should be used rather than
 *  pointer-safe access. This type of design should be directly enforced at a higher level, typically
 *  on the half-edge mesh.
 *
 @sa The HalfEdgeVertex class that represents half-edge vertices.
 */
template <class T>
class HalfEdgeVertexAccessor {
	//! The half-edge vertex accessor class is friend of the HalfEdgeMesh class to enable direct data access
	friend class HalfEdgeMesh< HalfEdge<T> >;

public:
	HalfEdgeVertexAccessor(const HalfEdgeVertex<T>& vertex);
	virtual ~HalfEdgeVertexAccessor();

	HalfEdgeAccessor<T> leaving_edge() const;
	const T& location() const;

private:
	HalfEdgeVertexAccessor(const HalfEdgeVertexAccessor& rhs);
	HalfEdgeVertexAccessor& operator=(const HalfEdgeVertexAccessor& rhs);

protected:
	//! Face associated to this accessor
	const HalfEdgeVertex<T>& vertex_;
};

//=================================================================================

#ifdef GAMEENGINE_NAMESPACES
} // namespace GameEngine
#endif

#include <GameEngine/Geometry/Topology/halfedge_accessor.hpp>

#endif
